#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <time.h>

#define READER_NUM 5
#define WRITER_NUM 3
#define OPERATION_NUM 3

pthread_mutex_t mutex;      // 保护read_count的互斥锁
pthread_mutex_t rw_mutex;   // 读写互斥锁
int read_count = 0;         // 当前读者数量
int shared_data = 0;        // 共享数据

// 读者可以多个人一起读
// 也就是当有一个读者获得读写锁，其他的读者也可以可以进行读，当所有的读者都读完后，才释放读写锁，这是读者优先。
// 写者最多只能一个人写
// 写者不仅和读者竞争读写锁，也和其他写者竞争读写锁

// 读者线程函数
void *reader(void *arg) {
    int id = *(int *)arg;

    int flag = 1;

    while (1) {
        // 模拟读者处理其他事情
        usleep(rand() % 100000);

        // 进入临界区
        pthread_mutex_lock(&mutex);
        read_count++;
        if (read_count == 1) {
            pthread_mutex_lock(&rw_mutex); // 第一个读者需要获取读写锁
        }
        pthread_mutex_unlock(&mutex);

        // 读取共享数据
        printf("读者 %d 读取数据: %d (当前读者数: %d)\n", id, shared_data, read_count);

        // if(flag == 1)
        // {
        //     sleep(1);
        //     flag = 0;
        // }
        usleep(rand() % 100000);

        // 离开临界区
        pthread_mutex_lock(&mutex);
        read_count--;
        if (read_count == 0) {
            pthread_mutex_unlock(&rw_mutex); // 最后一个读者释放读写锁
        }
        pthread_mutex_unlock(&mutex);
    }

    return NULL;
}

// 写者线程函数
void *writer(void *arg) {
    int id = *(int *)arg;

    sleep(2);

    while(1) {
        // 模拟写者处理其他事情
        usleep(rand() % 100000);

        // 获取读写锁
        pthread_mutex_lock(&rw_mutex);

        // 写入共享数据
        shared_data++;
        printf("写者 %d 写入数据: %d\n", id, shared_data);

        // 释放读写锁
        pthread_mutex_unlock(&rw_mutex);
    }

    return NULL;
}

int main() {
    pthread_t readers[READER_NUM];
    pthread_t writers[WRITER_NUM];
    int reader_ids[READER_NUM];
    int writer_ids[WRITER_NUM];

    // 初始化随机数种子
    srand(time(NULL));

    // 初始化互斥锁
    pthread_mutex_init(&mutex, NULL);
    pthread_mutex_init(&rw_mutex, NULL);

    // 创建读者线程
    for (int i = 0; i < READER_NUM; i++) {
        reader_ids[i] = i + 1;
        pthread_create(&readers[i], NULL, reader, &reader_ids[i]);
    }

    // 创建写者线程
    for (int i = 0; i < WRITER_NUM; i++) {
        writer_ids[i] = i + 1;
        pthread_create(&writers[i], NULL, writer, &writer_ids[i]);
    }

    // 等待读者线程结束
    for (int i = 0; i < READER_NUM; i++) {
        pthread_join(readers[i], NULL);
    }

    // 等待写者线程结束
    for (int i = 0; i < WRITER_NUM; i++) {
        pthread_join(writers[i], NULL);
    }

    // 销毁互斥锁
    pthread_mutex_destroy(&mutex);
    pthread_mutex_destroy(&rw_mutex);

    printf("所有线程执行完毕，最终共享数据值: %d\n", shared_data);

    return 0;
}